use std::collections::HashMap;

pub type Constructor<T, Args> = fn(&Args) -> T;

pub struct Factory<T, Args> {
    constructor_map:HashMap<String, Constructor<T, Args>>,
}

impl<T, Args> Factory<T, Args> {
    pub fn new() -> Self {
        Self { constructor_map: HashMap::new() }
    }

    pub fn register(&mut self, name:&str, f:Constructor<T, Args>) {
        if self.constructor_map.insert(name.to_string(), f).is_some() {
            panic!("duplicate name:{}", name);
        }
    }

    pub fn make_product(&self, name:&str, args:Args) -> Option<T> {
        self.constructor_map.get(name).map(|f|f(&args))
    }
}